package com.demo.function.spring.feign.log;

import feign.Logger;
import feign.Request;
import feign.Response;
import feign.Util;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static feign.Util.UTF_8;
import static feign.Util.decodeOrDefault;

/**
 * feign日志记录
 */
@Slf4j
public class FeignLogger extends Logger {

    @Override
    protected void log(String configKey, String format, Object... args) {
    }

    /**
     * 请求日志记录
     * @param configKey 调用Feign的类和方法名
     * @param logLevel 日志输出等级
     * @param request 请求对象
     */
    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {
        String url = request.url();
        String method = request.httpMethod().name();
        String bodyText = request.charset() != null ? new String(request.body(), request.charset()) : "";

        log.info("feign class:{}, 请求url:{},method:{},body:{}", configKey, url, method, bodyText);
    }

    /**
     * 响应日志记录
     * @param configKey 调用Feign的类和方法名
     * @param logLevel 日志输出等级
     * @param response 响应对象
     * @param elapsedTime 响应时间，毫秒级
     * @return 返回响应对象
     * @throws IOException 抛出IO异常
     */
    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime) throws IOException {
        Request request = response.request();
        int status = response.status();
        String url = request.url();
        String method = request.httpMethod().name();
        int bodyLength;
        if (response.body() != null && !(status == 204 || status == 205)) {
            String bodyText = "";

            // HTTP 204 No Content "...response MUST NOT include a message-body"
            // HTTP 205 Reset Content "...response MUST NOT include an entity"
            byte[] bodyData = Util.toByteArray(response.body().asInputStream());
            bodyLength = bodyData.length;
            if (bodyLength > 0) {
                bodyText = decodeOrDefault(bodyData, UTF_8, "Binary data");
            }
            log.info("feign class:{}, 请求url:{},method:{},返回结果:{}, 响应时间:{}毫秒", configKey, url, method, bodyText, elapsedTime);
            return response.toBuilder().body(bodyData).build();
        }
        log.info("feign class:{}, 请求url:{}, method:{}, 状态:{}, 响应时间:{}毫秒", configKey, url, method, status, elapsedTime);
        return response;
    }
}
